package main

import (
	"context"
	"fmt"
	"gitee.com/jinmingzhi/eth-learn/pkg/ethtool"
	"github.com/ethereum/go-ethereum/accounts/abi"
	"github.com/ethereum/go-ethereum/common"
	"io/ioutil"
	"math/big"
	"strings"
)

var (
	url      = "http://localhost:8545"
	fileDir  = "/Users/jinmingzhi/eth-learn/5day/build"
	abiBytes []byte
	binByte  []byte
	ctx      = context.Background()
	client   *ethtool.Client
)

func main() {
	loadContract()
	dial()
	ctx := context.Background()
	accounts, err := client.EthAccounts(ctx)
	assert(err)

	//ABI编码
	tokenAbi, _ := abi.JSON(strings.NewReader(string(abiBytes))) //创建ABI编解码器
	data,_ := tokenAbi.Pack(                           //编码方法调用
		"transfer",                               //合约方法名
		accounts[1],                              //合约方法参数1
		big.NewInt(100),                          //合约方法参数2
	)
	//data = append(binByte, data...)

	// 合约 msg
	msg := map[string]interface{}{
		"from": accounts[0],            //交易发起账号：节点第1个账号
		"to":   loadContractAddres(),   //合约部署地址
		"data": common.Bytes2Hex(data), //abi编码后的合约方法调用
		"gas":  big.NewInt(200000),     //交易gas上限
	}
	txid, _ := client.EthSendTransaction(context.Background(), msg) //发送交易
	fmt.Println("txid:", txid)




	// call
	data,_ = tokenAbi.Pack(                 //编码合约方法调用
		"balanceOf",                  //合约方法名
		accounts[0],                  //合约方法参数1
	)
	msg = map[string]interface{}{
		"from": accounts[0],                            //交易发起账号
		"to": loadContractAddres(),                          //合约部署地址
		"data": common.Bytes2Hex(data),             //ABI编码后的合约方法调用数据
		"gas": big.NewInt(200000),                      //交易gas上限
	}
	ret,_ := client.EthCall(context.Background(),msg) //调用合约只读方法

	fmt.Println("res:", string(ret))
	// unpack
	var balancePtr = new(*big.Int)
	err = tokenAbi.UnpackIntoInterface(balancePtr, "balanceOf", ret)
	assert(err)
	fmt.Println("balance:", *balancePtr)
}

func dial() {
	var err error
	client, err = ethtool.Dial(url)
	assert(err)
}

func loadContract() {
	var err error
	abiBytes, err = ioutil.ReadFile(fileDir + "/EzToken.abi")
	assert(err)
	//var binHexBytes []byte
	//binHexBytes, err = ioutil.ReadFile(fileDir + "/EzToken.bin")
	//assert(err)
	//
	//binByte = common.Hex2Bytes(string(binHexBytes))
}

func loadContractAddres() common.Address {
	addressBytes, err := ioutil.ReadFile(fileDir + "/EzToken.address")
	assert(err)
	return common.BytesToAddress(addressBytes)
}

func assert(err error) {
	if err != nil {
		panic(err)
	}
}
